package com.service;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.misc.Tool;
import com.type.Activity;
import com.type.Comment;
import com.type.Commenter;
import com.type.Follower;
import com.type.Photo;
import com.type.User;
import com.type.newTypeUser;

public class SocketSession extends Thread {
	// constant
	static final int REGISTER_INTERACT = 101;
	static final int LOGIN_ACCOUNT_INTERACT = 102;

	static final int PROVIDE_ONLINE_FACEBOOK_FRIEND = 1;
	static final int PROVIDE_ONLINE_FRIEND = 2;
	static final int RECEIVE_CREATED_TOPIC = 3;
	static final int PROVIDE_FRIEND_CREATED_ACTIVITY = 4;
	static final int RECEIVE_JOIN_ACTIVITY = 5;
	static final int RECEIVE_ADD_COMMENT = 6;
	static final int PROVIDE_FOLLOW_AND_COMMENT_DETAIL = 7;
	
	// field
	Socket socket;
	DataOutputStream dos;
	DataInputStream dis;

	HashMap<Long, User> userMap;
	HashMap<Long, Activity> tempActivityList;
	
	final int PROVIDE_FACEBOOK_FRIEND_LIST = 120;
	final int TRANSFERRING_FACEBOOK_FRIEND = 5001;
	final int NOT_FOUND_FACEBOOK_FRIEND = 5002;
	final int FOUND_FACEBOOK_FRIEND = 5003;
	Boolean isFoundFbFriend = false;

	Db db;
	
	
	public SocketSession(Socket socket, HashMap<Long, User> userMap) throws IOException, SQLException {
		this.socket = socket;
		this.userMap = userMap;
		dos = new DataOutputStream(socket.getOutputStream());
		dis = new DataInputStream(socket.getInputStream());
		db = new Db();
	}

	
	public void run() {
		try {
			switch (dis.readInt()) {
			case REGISTER_INTERACT:
				registerInteract();
				break;
			case LOGIN_ACCOUNT_INTERACT:
				loginAccount();
				break;
			case PROVIDE_ONLINE_FRIEND:
				provideOnlineFriend();
				break;
			case PROVIDE_FACEBOOK_FRIEND_LIST:
				provideFacebookFriendList();
				break;
			case RECEIVE_CREATED_TOPIC:
				receiveCreatedTopic();
				break;
			case PROVIDE_FRIEND_CREATED_ACTIVITY:
				provideFriendCreatedActivity();
				break;
			case RECEIVE_JOIN_ACTIVITY:
				receiveJoinActivity();
				break;
			case RECEIVE_ADD_COMMENT:
				receiveAddComment();
				break;
			case PROVIDE_FOLLOW_AND_COMMENT_DETAIL:
				provideFollowAndCommentDetail();
			default:
				break;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				dis.close();
				dos.close();
				socket.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}

	
	void registerInteract() throws IOException, InterruptedException, SQLException {
		long phoneNumber = dis.readLong();
		String password = dis.readUTF();
		String name = dis.readUTF();
		byte[] byteArray = Tool.receiveByteArray(dis);
		dos.writeBoolean(db.insertNewUser(phoneNumber, password, name, byteArray, true));
	}
	
	
	void loginAccount() throws IOException, SQLException, InterruptedException {
		long phoneNumber = dis.readLong();
		if(db.isExistAccount(phoneNumber)) {
			dos.writeBoolean(true);
			String password = dis.readUTF();
			newTypeUser dataPackage = db.validateAccount(phoneNumber, password);
			if(dataPackage != null) {
				dos.writeBoolean(true);
				dos.writeUTF(dataPackage.getName());
				Tool.sendByteArray(dos, dataPackage.getAvatar());
			} else
				dos.writeBoolean(false);
		} else
			dos.writeBoolean(false);
	}
	

	@SuppressWarnings("rawtypes")
	void provideFacebookFriendList() throws InterruptedException, IOException {
		ArrayList<User> userList = new ArrayList<User>();
		
		int facebookFriendCount = dis.readInt();
		if (facebookFriendCount > 0) {
			for (int i = 0; i < facebookFriendCount; i++) {
				long facebookUserId = Long.parseLong(dis.readUTF());
				
				Iterator iter = userMap.entrySet().iterator();
				while (iter.hasNext()) {
					Map.Entry entry = (Map.Entry) iter.next();
					User user = (User) entry.getValue();
					if (user.getFacebookUserId() == facebookUserId)
						userList.add(user);
				}
			}
			
			if(userList.isEmpty())
				dos.writeInt(0);
			else {
				dos.writeInt(userList.size());
				for (User matchedUser : userList)
					matchedUser.send(dos);
			}
		}
	}


	public void provideOnlineFriend() throws IOException, InterruptedException, SQLException {
		int size = dis.readInt();
		for(int i=0; i<size; i++) {
			long friendPhoneNum = dis.readLong();
			newTypeUser dataPackage = db.findFriend(friendPhoneNum);
			if(dataPackage != null) {
				dos.writeBoolean(true);
				dos.writeLong(friendPhoneNum);
				dos.writeUTF(dataPackage.getName());
				Tool.sendByteArray(dos, dataPackage.getAvatar());
			} else
				dos.writeBoolean(false);
		}
	}
	

	void receiveCreatedTopic() throws IOException, InterruptedException {
		long phoneNum = dis.readLong();
		String title = dis.readUTF();
		String content = dis.readUTF();
		byte[] byteArray = Tool.receiveByteArray(dis);
		db.receiveCreatedTopic(phoneNum, title, content, byteArray);
	}
	
	
	void provideFriendCreatedActivity() throws IOException, InterruptedException {
		ArrayList<Activity> activityList = userMap.get(dis.readLong()).getActivityList();
		if(activityList.isEmpty())
			dos.writeInt(0);
		else {
			dos.writeInt(activityList.size());
			for(Activity activity : activityList)
				activity.send(dos);
		}
	}


	void receiveJoinActivity() throws IOException {
		User user = userMap.get(dis.readLong());
		Activity activity = user.getActivityList().get(dis.readInt());
		activity.getFollowList().add(new Follower(dis.readLong()));
	}
	
	
	void receiveAddComment() throws IOException, InterruptedException {
		User user = userMap.get(dis.readLong());
		ArrayList<Follower> followList = user.getActivityList().get(dis.readInt()).getFollowList();
		long commenterNum = dis.readLong();
		int i=0;
		for( ; i < followList.size(); i++)
			if(followList.get(i).getPhoneNumber() == commenterNum)
				break;
		
		String textComment = dis.readUTF();
		Photo photoComment = new Photo();
		photoComment.receive(dis);
		Comment comment = new Comment(textComment, photoComment);
		
		if(followList.get(i) instanceof Commenter) {
			Commenter commenter = (Commenter)followList.get(i);
			commenter.getCommentList().add(comment);
		} else if (followList.get(i) instanceof Follower) {
			Commenter newCommenter = new Commenter(commenterNum, comment);
			followList.set(i, newCommenter);
		}
	}
	
	
	void provideFollowAndCommentDetail() throws IOException, InterruptedException {
		User user = userMap.get(dis.readLong());
		ArrayList<Follower> followList = user.getActivityList().get(dis.readInt()).getFollowList();
		if(followList.isEmpty())
			dos.writeInt(0);
		else {
			dos.writeInt(followList.size());
			for (int i = 0; i < followList.size(); i++) {
				if (followList.get(i) instanceof Commenter) {
					dos.writeBoolean(true);
					Commenter commenter = (Commenter) followList.get(i);
					commenter.send(dos);
				} else if (followList.get(i) instanceof Follower) {
					dos.writeBoolean(false);
					Follower follower = (Follower) followList.get(i);
					follower.send(dos);
				}
			}
		}
	}
}
